package com.haixiaoke.smartLock.haixiaoke;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.haixiaoke.common.core.domain.AjaxResult;
import com.haixiaoke.common.exception.ServiceException;
import com.haixiaoke.common.utils.StringUtils;
import com.haixiaoke.domain.*;
import com.haixiaoke.service.*;
import com.haixiaoke.vo.YltAuthVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static cn.hutool.crypto.SecureUtil.sha1;

/**
 * 嗨小克接口事件处理
 * &#064;Author  panda
 * &#064;Date  2023/8/18
 **/
@Slf4j
@Service
public class SmartLockHXKEventHandleService {
    @Autowired
    private SmartLockHXKService smartLockHXKService;
    @Autowired
    private ILockYltAccreditService lockYltAccreditService;
    @Autowired
    private ISmartLockService smartLockService;

    @Autowired
    private ISmartLockCardService iSmartLockCardService;
    @Autowired
    private ISmartLockPwdService iSmartLockPwdService;
    @Autowired
    private ISmartLockFaceService iSmartLockFaceService;

    /**
     * 嗨小克授权密码
     * @param smartLockPwd
     * @return
     */
    public int insertSmartLockPwd(SmartLockPwd smartLockPwd) {
        String password = smartLockPwd.getPassword();
        if (SmartLockPwd.PASSWORD_GENERATE_TYPE_SYSGEN.equals(smartLockPwd.getGenerateType())) {
            password = RandomUtil.randomNumbers(6);
        } else {
            if (StrUtil.isEmpty(password)) {
                throw new ServiceException("密码不能为空");
            }
            if (password.length() != 6 || !StringUtils.isNumeric(smartLockPwd.getPassword())) {
                throw new ServiceException("请输入6位数字密码");
            }
        }

        SmartLock smartLock = new SmartLock();
        YltAuthVo yltAuthVo = lockYltAccreditService.getYLTAuthInfoBySNAndIdentification(smartLockPwd.getSn(), smartLockPwd.getIdentification());
        if (ObjectUtil.isNotEmpty(yltAuthVo)) {
            if (yltAuthVo.getFOpenByPassword().equals(LockYltAccredit.AUTH_STATE_TRUE)) {
                throw new ServiceException("用户密码已授权");
            }

            Date fBeginDate = yltAuthVo.getFBeginDate();
            Date fEndDate = yltAuthVo.getFEndDate();
            if (!smartLockPwd.getStartTime().equals(fBeginDate) || !smartLockPwd.getEndTime().equals(fEndDate)) {
                throw new ServiceException("授权时间与用户授权时间不一致");
            }
            smartLock.setSn(smartLockPwd.getSn());
            smartLock.setIdentification(smartLockPwd.getIdentification());
            smartLock.setPassword(password);
            smartLock.setYltAuthVo(yltAuthVo);

        } else {
            if (smartLockPwd.getStartTime() != null && smartLockPwd.getEndTime() != null && smartLockPwd.getStartTime().after(smartLockPwd.getEndTime())) {
                throw new ServiceException("授权时间有误!");
            }
            smartLock.setSn(smartLockPwd.getSn());
            smartLock.setIdentification(smartLockPwd.getIdentification());
            smartLock.setStartTime(smartLockPwd.getStartTime());
            smartLock.setEndTime(smartLockPwd.getEndTime());
            smartLock.setPassword(password);

            // 构建参数
            yltAuthVo = YltAuthVo.createDefault();
            yltAuthVo.setFBeginDate(smartLockPwd.getStartTime());
            yltAuthVo.setFEndDate(smartLockPwd.getEndTime() );
            yltAuthVo.setFAppUserID(smartLockPwd.getIdentification());
            smartLock.setYltAuthVo(yltAuthVo);
        }
        return Integer.parseInt(smartLockHXKService.addPassword(smartLock));
    }

    /**
     * 嗨小克删除密码
     * @param sn
     * @param identification
     * @return
     */
    public int deleteSmartLockPwd(String sn, String identification) {

        YltAuthVo yltAuthVo = lockYltAccreditService.getYLTAuthInfoBySNAndIdentification(sn, identification);
        SmartLock smartLock = new SmartLock();
        smartLock.setSn(sn);
        smartLock.setYltAuthVo(yltAuthVo);
        smartLock.setIdentification(identification);

        return Integer.parseInt(smartLockHXKService.deletePwd(smartLock));
    }

    /**
     * 嗨小克授权人脸
     * @param smartLockFace
     * @return
     */
    public int insertSmartLockFace(SmartLockFace smartLockFace) {
        SmartLock smartLock = new SmartLock();
        YltAuthVo yltAuthVo = lockYltAccreditService.getYLTAuthInfoBySNAndIdentification(smartLockFace.getSn(), smartLockFace.getIdentification());
        if (ObjectUtil.isNotEmpty(yltAuthVo)) {
            if (yltAuthVo.getFOpenByPassword().equals(LockYltAccredit.AUTH_STATE_TRUE)) {
                throw new ServiceException("用户密码已授权");
            }

            Date fBeginDate = yltAuthVo.getFBeginDate();
            Date fEndDate = yltAuthVo.getFEndDate();
            /*if (!smartLockFace.getStartTime().equals(fBeginDate) || !smartLockFace.getEndTime().equals(fEndDate)) {
                throw new RuntimeException("授权时间与用户授权时间不一致");
            }*/
            smartLock.setSn(smartLockFace.getSn());
            smartLock.setIdentification(smartLockFace.getIdentification());
            smartLock.setFaceImage(smartLockFace.getFaceImage());
            // 构建参数
            yltAuthVo = YltAuthVo.createDefault();
            yltAuthVo.setFBeginDate(smartLockFace.getStartTime());
            yltAuthVo.setFEndDate(smartLockFace.getEndTime() );
            yltAuthVo.setFAppUserID(smartLockFace.getIdentification());
            smartLock.setYltAuthVo(yltAuthVo);
        } else {
            if (smartLockFace.getStartTime() != null && smartLockFace.getEndTime() != null && smartLockFace.getStartTime().after(smartLockFace.getEndTime())) {
                throw new ServiceException("授权时间有误!");
            }
            smartLock.setSn(smartLockFace.getSn());
            smartLock.setIdentification(smartLockFace.getIdentification());
            smartLock.setStartTime(smartLockFace.getStartTime());
            smartLock.setEndTime(smartLockFace.getEndTime());
            smartLock.setFaceImage(smartLockFace.getFaceImage());

            // 构建参数
            yltAuthVo = YltAuthVo.createDefault();
            yltAuthVo.setFBeginDate(smartLockFace.getStartTime());
            yltAuthVo.setFEndDate(smartLockFace.getEndTime() );
            yltAuthVo.setFAppUserID(smartLockFace.getIdentification());
            smartLock.setYltAuthVo(yltAuthVo);
        }
        return Integer.parseInt(smartLockHXKService.addFaceImage(smartLock));
    }

    /**
     * 嗨小克删除人脸授权
     * @param sn
     * @param identification
     * @return
     */
    public int deleteSmartLockFace(String sn, String identification) {
        YltAuthVo yltAuthVo = lockYltAccreditService.getYLTAuthInfoBySNAndIdentification(sn, identification);
        if (ObjectUtil.isEmpty(yltAuthVo)) {
            throw new ServiceException("授权信息查询失败");
        }
        SmartLock smartLock = new SmartLock();
        smartLock.setSn(sn);
        smartLock.setYltAuthVo(yltAuthVo);
        smartLock.setIdentification(identification);

        return Integer.parseInt(smartLockHXKService.deleteFace(smartLock));
    }

    /**
     * 嗨小克门卡、身份证授权
     * @param smartLockCard
     * @return
     */
    public int insertSmartLockCard(SmartLockCard smartLockCard) {
        if (StrUtil.isEmpty(smartLockCard.getIdentification()) || StrUtil.isEmpty(smartLockCard.getSn()) ||
                StrUtil.isEmpty(smartLockCard.getCardNumber()) || ObjectUtil.isNull(smartLockCard.getCardType())) {
            throw new ServiceException("参数有误");
        }
        Date startTime = smartLockCard.getStartTime();
        Date endTime = smartLockCard.getEndTime();

        String result = "";
        SmartLock smartLock = new SmartLock();
        YltAuthVo yltAuthVo = lockYltAccreditService.getYLTAuthInfoBySNAndIdentification(smartLockCard.getSn(), smartLockCard.getIdentification());
        if (ObjectUtil.isNotEmpty(yltAuthVo)) {
            if (SmartLockCard.IDENTITY_CARD_TYPE.equals(smartLockCard.getCardType())) {
                Integer fOpenByIDCard = yltAuthVo.getFOpenByIDCard();
                if (fOpenByIDCard.equals(LockYltAccredit.AUTH_STATE_TRUE)) {
                    throw new ServiceException("用户身份证已授权");
                }
            } else {
                Integer fOpenByICCard = yltAuthVo.getFOpenByICCard();
                if (fOpenByICCard.equals(LockYltAccredit.AUTH_STATE_TRUE)) {
                    throw new ServiceException("用户ic卡已授权");
                }
            }

            Date fBeginDate = yltAuthVo.getFBeginDate();
            Date fEndDate = yltAuthVo.getFEndDate();
            if (!startTime.equals(fBeginDate) || !endTime.equals(fEndDate)) {
                throw new ServiceException("授权时间与用户授权时间不一致");
            }
            smartLock.setSn(smartLockCard.getSn());
            smartLock.setIdentification(smartLockCard.getCardNumber());
            smartLock.setCardNumber(smartLockCard.getCardNumber());
            smartLock.setYltAuthVo(yltAuthVo);
            smartLock.setCardType(smartLockCard.getCardType());
        } else {
            if (ObjectUtil.isNull(startTime) || ObjectUtil.isNull(endTime)) {
                throw new ServiceException("授权时间有误!");
            }
            smartLock.setSn(smartLockCard.getSn());
            smartLock.setIdentification(smartLockCard.getCardNumber());
            smartLock.setStartTime(startTime);
            smartLock.setEndTime(endTime);
            smartLock.setCardNumber(smartLockCard.getCardNumber());

            // 构建参数
            yltAuthVo = YltAuthVo.createDefault();
            yltAuthVo.setFBeginDate(startTime);
            yltAuthVo.setFEndDate(endTime);
            yltAuthVo.setFAppUserID(smartLock.getCardNumber());
            yltAuthVo.setFLockMAC(smartLockCard.getSn());
            smartLock.setYltAuthVo(yltAuthVo);
            smartLock.setCardType(smartLockCard.getCardType());
        }
        return Integer.parseInt(smartLockHXKService.addCard(smartLock));
    }

    /**
     * 嗨小克门卡、身份证删除授权
     * @param smartLockCard
     * @return
     */
    public int deleteSmartLockCard(SmartLockCard smartLockCard) {
        YltAuthVo yltAuthVo = lockYltAccreditService.getYLTAuthInfoBySNAndIdentification(smartLockCard.getSn(), smartLockCard.getIdentification());
        SmartLock smartLock = new SmartLock();
        smartLock.setSn(smartLockCard.getSn());
        smartLock.setYltAuthVo(yltAuthVo);
        smartLock.setCardType(smartLockCard.getCardType());
        smartLock.setIdentification(smartLockCard.getIdentification());
        return Integer.parseInt(smartLockHXKService.deleteCard(smartLock));
    }

    /**
     * 嗨小克删除该锁下的所有授权信息
     * @param smartLock
     * @return
     */
    public Integer deleteSmartLockByLockId(SmartLock smartLock) {
        if (StrUtil.isEmpty(smartLock.getSn())) {
            log.error("嗨小克该锁的sn数据为空");
            return 0;
        }
        smartLock.setDeleteUserFlag(true);
        return Integer.parseInt(smartLockHXKService.deleteAuthAll(smartLock));
    }

    public List<SmartLockDetails> selectSmartLockBySn(String sn) {
        List<SmartLockCard> smartLockCards = iSmartLockCardService.selectSmartLockCardBySN(sn);
        List<SmartLockDetails> list = new ArrayList<>();
        for (SmartLockCard smartLockCard : smartLockCards) {
            SmartLockDetails details = new SmartLockDetails();
            details.setCardType(smartLockCard.getCardType());
            details.setIdentification(smartLockCard.getIdentification());
            details.setStartTime(DateUtil.format(smartLockCard.getStartTime(), "yyyy-MM-dd HH:mm:ss"));
            details.setEndTime(DateUtil.format(smartLockCard.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
            details.setCreateAt(DateUtil.format(smartLockCard.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            list.add(details);
        }
        return list;
    }

    public List<SmartLockDetails> getLockPassword(String sn) {
        List<SmartLockDetails> list = new ArrayList<>();
        List<SmartLockPwd> smartLockPwds = iSmartLockPwdService.selectSmartLockPwdBySN(sn);

        for (SmartLockPwd pwd : smartLockPwds) {
            SmartLockDetails details = new SmartLockDetails();
            details.setPassword(pwd.getPassword());
            details.setIdentification(pwd.getIdentification());
            details.setStartTime(DateUtil.format(pwd.getStartTime(), "yyyy-MM-dd HH:mm:ss"));
            details.setEndTime(DateUtil.format(pwd.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
            details.setCreateAt(DateUtil.format(pwd.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            list.add(details);
        }
        return list;
    }

    public String selectSmartLockList(SmartLock smartLock) {
        return smartLockHXKService.getSmartLockByLockName(smartLock);
    }

    public String selectTaskList(SmartLock smartLock){
        if (smartLock.getStartTime() == null || smartLock.getEndTime() == null) {
            Calendar instance = Calendar.getInstance();
            smartLock.setEndTime(instance.getTime());
            instance.add(Calendar.YEAR,-1);
            smartLock.setStartTime(instance.getTime());
        }
        return smartLockHXKService.getTaskList(smartLock);
    }

    public Integer insertSmartLockAll(SmartLock smartLock) {
        YltAuthVo yltAuthVo = YltAuthVo.createDefault();
        yltAuthVo.setFBeginDate(smartLock.getStartTime());
        yltAuthVo.setFEndDate(smartLock.getEndTime() );
        yltAuthVo.setFAppUserID(smartLock.getIdentification());
        //人脸授权
        if (StrUtil.isNotEmpty(smartLock.getFaceImage())) {
            // 构建参数
            yltAuthVo.setFOpenByFace(LockYltAccredit.AUTH_STATE_TRUE);
            yltAuthVo.setFaceImage(smartLock.getFaceImage());
        }
        //密码授权
        if (StrUtil.isNotEmpty(smartLock.getPassword())) {
            yltAuthVo.setFOpenByPassword(LockYltAccredit.AUTH_STATE_TRUE);
            yltAuthVo.setFOpenPassword(smartLock.getPassword());
        }
        //门卡授权
        if (StrUtil.isNotEmpty(smartLock.getCardNumber())) {
            if (SmartLock.CPU_CARD_TYPE.equals(smartLock.getCardType())) {
                yltAuthVo.setFOpenByICCard(LockYltAccredit.AUTH_STATE_TRUE);
                yltAuthVo.setFICCardNumber(smartLock.getCardNumber());
            } else if (SmartLock.IDENTITY_CARD_TYPE.equals(smartLock.getCardType())) {
                yltAuthVo.setFOpenByIDCard(LockYltAccredit.AUTH_STATE_TRUE);
                yltAuthVo.setFIDCardID(smartLock.getCardNumber());
            } else {
                log.error("五代锁--授权门卡数据异常：cardType：{}", smartLock.getCardType());
                throw new ServiceException("五代锁--授权门卡数据异常");
            }
        }
        smartLock.setYltAuthVo(yltAuthVo);
        return Integer.parseInt(smartLockHXKService.addAuth(smartLock));
    }

    public Integer remoteUnlock(SmartLock smartLock) {
        return Integer.parseInt(smartLockHXKService.remoteUnlock(smartLock));
    }

    public Integer setSecretKey(SmartLock smartLock) {
        return Integer.parseInt(smartLockHXKService.setSecretKey(smartLock));
    }

    public Integer lockReset(SmartLock smartLock) {
        return Integer.parseInt(smartLockHXKService.lockReset(smartLock));
    }

    public Integer removeUser(SmartLock smartLock) {
        YltAuthVo yltAuthVo = YltAuthVo.createDefault();
        yltAuthVo.setFAppUserID(smartLock.getIdentification());
        smartLock.setYltAuthVo(yltAuthVo);
        return Integer.parseInt(smartLockHXKService.deleteAuth(smartLock));
    }

    public Integer removeUserAll(SmartLock smartLock) {
        int result = Integer.parseInt(smartLockHXKService.deleteAuthAll(smartLock));
        if (1 == result) {
            smartLockHXKService.deleteAppletSmartAuth(smartLock);
        }
        return result;
    }

    public AjaxResult offlinePwd(SmartLock smartLock) {
        String result = "";
        String secretKey = "";
        if (StrUtil.isEmpty(smartLock.getSn())) {
            return AjaxResult.error("设备的mac为空");
        }
        if (StrUtil.isEmpty(smartLock.getSecretKey())) {
            smartLock.setPageSize(1);
            smartLock.setPageNum(1);
            String resultBody = smartLockHXKService.getSmartLock(smartLock);
            if (StrUtil.isNotEmpty(resultBody)) {
                JSONObject resultObject = JSONObject.parseObject(resultBody);
                String resultData = resultObject.getString("result");
                if ("[]".equals(resultData)) {
                    log.error("查询不到该锁的设备信息，请求数据：{}",JSONObject.toJSONString(smartLock));
                    return AjaxResult.error("查询不到设备信息，设备异常！");
                } else {
                    List<lockResponse> jsonObject = JSONArray.parseArray(resultData,lockResponse.class);
                    secretKey = jsonObject.get(0).getSecretKey();
                    if (StrUtil.isEmpty(secretKey)) {
                        return AjaxResult.error("查询不到密钥信息，请先设置密钥信息！");
                    }
                }
            }
        }else {
            secretKey = smartLock.getSecretKey();
        }
        Date now = DateUtil.date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHH");
        String time ;
        if (now.getMinutes() < 10) {
            time = simpleDateFormat.format(now) + "00";
        } else {
            int a = (now.getMinutes() / 10 ) * 10;
            time = simpleDateFormat.format(now) + (a - a % 10);
        }

        //-----------------------------------
        //2023-08-11，wifi设备在计算离线密码时，需要使用后10位
        String mac = smartLock.getSn();
        if (mac.length() == 12) {
            mac = StrUtil.sub(mac, 2, 10);
//            mac = mac.substring(2, 10);
        }
        //data可以多种算法:mac，secretKey，time任意顺序相加，可随机用一种
        //如data=mac+secretKey+time或data=secretKey+mac+time
//            String data = GetRandomData(mac, secretKey, time);
//        String data = mac + secretKey + time;
        String data = getRandomData(mac,secretKey,time);
        if (mac.length() == 12) {
            data = data.toLowerCase();
        }
        //计算sha1
        String encryptString = sha1(data);
        //按字节输出
        String strOut = "";
        if (encryptString.length() == 40) {

            strOut = StrUtil.sub(encryptString, 6, 6 + 2)
                    + StrUtil.sub(encryptString, 4, 4 + 2)
                    + StrUtil.sub(encryptString, 2, 2 + 2)
                    + StrUtil.sub(encryptString, 0, 2)

                    + StrUtil.sub(encryptString, 14, 14 + 2)
                    + StrUtil.sub(encryptString, 12, 12 + 2)
                    + StrUtil.sub(encryptString, 10, 10 + 2)
                    + StrUtil.sub(encryptString, 8, 8 + 2)

                    + StrUtil.sub(encryptString, 22, 22 + 2)
                    + StrUtil.sub(encryptString, 20, 20 + 2)
                    + StrUtil.sub(encryptString, 18, 18 + 2)
                    + StrUtil.sub(encryptString, 16, 16 + 2)

                    + StrUtil.sub(encryptString, 30, 30 + 2)
                    + StrUtil.sub(encryptString, 28, 28 + 2)
                    + StrUtil.sub(encryptString, 26, 26 + 2)
                    + StrUtil.sub(encryptString, 24, 24 + 2)

                    + StrUtil.sub(encryptString, 38, 38 + 2)
                    + StrUtil.sub(encryptString, 36, 36 + 2)
                    + StrUtil.sub(encryptString, 34, 34 + 2)
                    + StrUtil.sub(encryptString, 32, 32 + 2);

        }
        //每两个字节相异或再对10取模，得到10个字节，直接输前边8个数字给客户
        for (int i = 0; i < 40; i = i + 4) {

            String sub1 = StrUtil.sub(strOut, i, i + 2);
            String sub2 = StrUtil.sub(strOut, i + 2, i + 4);

            int h = Integer.parseInt(sub1, 16);
            int k = Integer.parseInt(sub2, 16);

            int v = h ^ k;
            int c = v % 10;
            result = result + c;
        }
        result = StrUtil.sub(result, 0, 8);
        log.info("嗨小克离线密码计算结果：{}",result);
        return AjaxResult.success(result);
    }

    private String getRandomData(String mac, String secretKey, String time) {
        int random = RandomUtils.nextInt(1, 7);
        log.info("嗨小克离线密码随机计算算法之和：{}",random);
        switch (random){
            case 1:
                return mac + secretKey + time;
            case 2:
                return mac + time + secretKey;
            case 3:
                return secretKey + mac + time;
            case 4:
                return secretKey + time + mac;
            case 5:
                return time + secretKey + mac;
            case 6:
                return time + mac + secretKey;
        }
        return mac + secretKey + time;
    }

    public Integer lockOTA(SmartLock smartLock) {
        return Integer.parseInt(smartLockHXKService.lockOTA(smartLock));
    }

    public int insertSmartLock(SmartLock smartLock) {
        String result = smartLockHXKService.getSmartLock(smartLock);
        Integer total = JSONObject.parseObject(result).getInteger("total");
        if (total == 0) {
            throw new ServiceException("注册失败，请检查设备SN是否正确");
        }
        return smartLockService.insertSmartLock(smartLock);
    }
}
